package edu.byu.isys413.jjenkins.data;
import java.net.InetAddress;
import java.util.StringTokenizer;
import java.util.Random; 
import java.lang.Byte;

/*******************************************************************************
 *  
 *  This class creates a unique identity based on IP address, system time, and
 *  counter. This identity should be worldy unique.
 *  Generates globally-unique identifiers    
 *  Author: Jeff Jenkins
 *  Version 1.0
 ******************************************************************************/

public class GUID {
    
  // Class Variables
    /**
     * system time
     */
   static long lstTime;     // static variable to hold the last time
    /**
     * number of guids purduced in a time period
     */
   static int intCounter;   // static variable to hold the counter value

    /**
     * unique identity
     */
   private GUID() { 
       // creates new GUID
  }

  /**
     *  Generates a new GUID 
     *  returns A unique GUID as a String
     * @throws java.lang.Exception 
     * @return GUID
     */
  public static synchronized String generate() throws Exception {
 
      //  declaration of local variables
      String strTime = "";      // to store  Hex Value
      String strCounter ="";    // to store counter 
      String strIp = "";        // to store IP Address
      long currentTime = System.currentTimeMillis();
      
      
      
       
    /***************************************************************************
     * Counter Code:compares last time to current time and increments counter if 
     * needed from a random start point. If counter is exhausted, the thread will 
     * sleep until the next milisecond. If times are not the same, the counter 
     * resets. The current time is then stored in a static variable.
     **************************************************************************/
      
      if(currentTime==lstTime){         
         if(intCounter == 16777215){ 
             while(currentTime==lstTime){
                 Thread.sleep(1);
                 intCounter = 0;
                 currentTime=System.currentTimeMillis();
                 
             } // end while 
         }  // end if (intCounter ==16777215)
         else{
             if(intCounter == 0){       
                 intCounter= (int)(Math.random()*1000);
             } // end else (intCounter ==16777215)
             else                     
                intCounter++;
        } // end els (intCounter ==lastTime)
     } // end if (currentTime==lstTime)
     else
         intCounter=0; 
    
     lstTime=currentTime;
     
     
     
     
     // Converts to Hex and adds zero
     strCounter= addZero(Integer.toHexString(intCounter), 6);           
                                               
      
      
    // Creates current time Id and adds zeroes         
     
     strTime = addZero(Long.toHexString(currentTime), 16);

     
    // Creates the ip address using the string Tokenizer id and adds zeros to the front 
     
     StringTokenizer st = new StringTokenizer(InetAddress.getLocalHost().getHostAddress(), ".");
   
     while (st.hasMoreTokens()) {
      strIp = strIp + addZero(Integer.toHexString(Integer.parseInt(st.nextToken())), 2);
      
    } // end while

     
      // Return GUID
      return(strTime+strCounter+strIp); 
      
      
  } // end generate
  
  
  /**
     *  Add Zeros to the end of a string for a given string length 
     *  returns a String
     *  parameter str = the string you want to add zeroes onto
     *  parameter number= the length you want the string to be
     * @param str string to add zeroes to
     * @param number the number of characters the string should be
     * @return new String
     */
  
private static String addZero(String str, int number){
     while(str.length() < number){
          str = "0" + str;
          } // end while
    return(str);
} // end addZero
} // end class
